<?php
/**
 * Created by PhpStorm.
 * User: Jan-Home
 * Date: 2018/10/20 0020
 * Time: 19:18
 */

use PHPUnit\Framework\TestCase;

require_once 'AnyClass.php';

class Test_TestClassInstanceTrait extends TestCase
{
	
	use \Ke\TestUtils\TestClassInstanceTrait;
	
	/**
	 * 初始化当前测试的测试实例
	 */
	protected function setUp()
	{
		$this->setTestInstance(new AnyClass());
	}
	
	/**
	 * 测试不存在的方法
	 */
	public function test_notExistsMethod()
	{
		$method = $this->newTestMethod('what');
		$this->assertFalse($method->isInvokable());
	}
	
	/**
	 * 测试存在的方法
	 */
	public function test_callExistsMethod()
	{
		$staticMethod = $this->newTestMethod('anyStaticMethod');
		$publicMethod = $this->newTestMethod('anyPublicMethod');
		$privateMethod = $this->newTestMethod('anyPrivateMethod');
		
		$this->assertSame(AnyClass::RET_STATIC_METHOD, $staticMethod->invoke());
		$this->assertSame(AnyClass::RET_PUBLIC_METHOD, $publicMethod->invoke());
		$this->assertSame(AnyClass::RET_PRIVATE_METHOD, $privateMethod->invoke());
	}
	
	/**
	 * 测试生成测试用例
	 */
	public function test_newTestItem()
	{
		$method = $this->newTestMethod('doSomeThing');
		
		$testItems = [
			$method->newTestItem("ok", "ok"),
			$method->newTestItem("abc", "abc"),
		];
		
		/** @var \Ke\TestUtils\TestItem $item */
		foreach ($testItems as $item) {
			$this->assertSame($item->getExcepted(), $item->invoke());
		}
	}
	
	/**
	 * 自定义测试
	 */
	public function test_customTest()
	{
		$method = $this->newTestMethod('doSomeThing');
		
		$testItems = [
			$method->newTestItem("ok", "ok", 'aaa'),
			$method->newTestItem("abc", "abc"),
			$method->newTestItem(function () { // 自定义测试
				echo "run in custom test", PHP_EOL;
				$this->assertNotEquals("what", "what2");
				$this->assertNotEquals(1, 2);
			}),
		];
		
		/** @var \Ke\TestUtils\TestItem $item */
		foreach ($testItems as $item) {
			$this->assertSame($item->getExcepted(), $item->invoke(), $item->getMessage());
		}
	}
	
	/**
	 * 测试调用注解测试方法
	 *
	 * @testMethod doSomeThing
	 * @throws \Ke\TestUtils\TestMethodException
	 */
	public function test_annotateGetMethod()
	{
		$method = $this->getLastAnnotationTestMethod();
		
		$testItems = [
			$method->newTestItem("ok", "ok", "ok的测试"),
			$method->newTestItem("abc", "abc", "abc的测试"),
		];
		
		/** @var \Ke\TestUtils\TestItem $item */
		foreach ($testItems as $item) {
			$this->assertSame($item->excepted, $item->invoke(), $item->message);
		}
	}
	
	/**
	 * 测试批量生成测试用例
	 */
	public function test_newItems()
	{
		$method = $this->newTestMethod('doSomeThing');
		$testItems = $method->newTestItems([
			['OK', 'ok', "ok的测试"],
			['ABC', 'abc', "abc的测试"],
			function (\Ke\TestUtils\TestMethod $method) {
				// 仍然获取到当前的测试方法
				echo "run in custom test, ";
				echo $method->invoke("ok"), PHP_EOL;
			},
		], function (AnyClass $obj, $index, \Ke\TestUtils\TestItem $item) {
			$item->setExcepted(mb_strtolower($item->excepted));
		});
		
		/** @var \Ke\TestUtils\TestItem $item */
		foreach ($testItems as $item) {
			$this->assertSame($item->excepted, $item->invoke(), $item->message);
		}
	}
	
	/**
	 * 测试直接针对某个方法执行测试方法
	 */
	public function test_runMethodTest()
	{
		$this->runMethodTest(
			'doSomeThing',
			[
				['OK', 'ok'],
				['ABC', 'abc'],
				['你好ABC', '你好abc'],
				function (\Ke\TestUtils\TestMethod $method) {
					// 仍然获取到当前的测试方法
					$this->assertSame('hello', $method->invoke('hello'));
				},
			],
			// 测试用例过滤回调函数
			function (AnyClass $obj, $index, \Ke\TestUtils\TestItem $item) {
				$item->setExcepted(mb_strtolower($item->excepted));
			},
			// 执行测试的实现回调函数
			function (AnyClass $obj, $index, \Ke\TestUtils\TestItem $item) {
				$this->assertSame($item->excepted, $item->invoke());
			}
		)->throwLastException(); // 尝试抛出最后的异常，phpunit是采用throw来抛出断言错误的，所以要确保phpunit正确运行仍要执行这个
	}

	/**
	 * 基于注解取得测试方法
	 *
	 * @testMethod doSomeThing
	 * @throws \Ke\TestUtils\TestMethodException
	 */
	public function test_runMethodTest_byAnnotation()
	{
		$this->runMethodTest(
			$this->getLastAnnotationTestMethod(),
			[
				['OK', 'ok'],
				['ABC', 'abc'],
				['你好ABC', '你好abc'],
				function (\Ke\TestUtils\TestMethod $method) {
					// 仍然获取到当前的测试方法
					$this->assertSame('hello', $method->invoke('hello'));
				},
			],
			// 测试用例过滤回调函数
			function (AnyClass $obj, $index, \Ke\TestUtils\TestItem $item) {
				$item->setExcepted(mb_strtolower($item->excepted));
			},
			// 执行测试的实现回调函数
			function (AnyClass $obj, $index, \Ke\TestUtils\TestItem $item) {
				$this->assertSame($item->excepted, $item->invoke());
			}
		)->throwLastException(); // 尝试抛出最后的异常，phpunit是采用throw来抛出断言错误的，所以要确保phpunit正确运行仍要执行这个
	}
}
